﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Web;
using Easy.Common;
using Easy.DAL;
using Easy.Model;
using Easy.Operation.Expression;
using Easy.Operation.Data;
using System.IO;
using System.Reflection;

namespace Easy.Operation
{

    #region 标准DataService对象
    /// <summary>
    /// 标准DataService对象
    /// </summary>
    public class DataService : System.Web.HttpApplication
    {
        private EntityDAL EntityDal;
        private CURD service;
        private string EntityName;
        private Guid CurrentUserId;
        private Guid CurrentBusinessId;

        public DataService(string entityName, Guid currentUserId)
        {
            if (string.IsNullOrWhiteSpace(entityName))
                throw new Exception(string.Format("EntityName Is NullOrWhiteSpace! "));
            this.EntityName = entityName.ToLower();
            this.CurrentUserId = currentUserId;
            this.CurrentBusinessId = new Guid(new SystemUserDAL().GetSystemUserById(currentUserId).Rows[0]["BusinessUnitId"].ToString());
            EntityDal = new EntityDAL(this.EntityName);
            service = new CURD(this.EntityName);

        }

        #region public方法

        /// <summary>
        /// 创建记录
        /// </summary>
        /// <param name="json">jsonEntity</param>
        /// <returns></returns>
        public string Create(string json)
        {
            Core core = new Core(EntityName);
            Dictionary<string, Field> allFields = core.GetFields();//当前实体的所有字段
            Dictionary<string, object> entityDic = JsonEntityToDictionary(json, allFields);

            return Create(entityDic, allFields).ToString();

        }

        /// <summary>
        /// 创建记录
        /// </summary>
        /// <param name="entityDic">字段及其赋值（字段名需全部小写）</param>
        /// <returns></returns>
        public string Create(Dictionary<string, object> entityDic)
        {
            Core core = new Core(EntityName);
            Dictionary<string, Field> allFields = core.GetFields();//当前实体的所有字段
            return Create(entityDic, allFields).ToString();
        }

        /// <summary>
        /// 根据主键值获取数据
        /// </summary>
        /// <param name="id">记录主键值</param>
        /// <param name="select">查找的字段集合</param>
        /// <returns></returns>
        public string Retrieve(Guid id, string[] select = null)
        {
            return JsonConvert.SerializeObject(Retrieve_Dic(id, select));
        }

        /// <summary>
        /// 根据主键值获取数据
        /// </summary>
        /// <param name="id">记录主键值</param>
        /// <param name="select">查找的字段集合</param>
        /// <returns></returns>
        public Dictionary<string, object> Retrieve_Dic(Guid id, string[] select = null)
        {
            if (!IsHaveRight(id, AccessRight.READ))
            {
                throw new CustomException(CustomExceptionState.NoReadPrivilege, "没有读取该记录的权限");
            }
            else
            {
                Core core = new Core(EntityName);
                Dictionary<string, Field> allFields = core.GetFields();//当前实体的所有字段
                string[] columns = select;
                if (select == null)
                {
                    columns = new string[allFields.Count];
                    int i = 0;
                    foreach (var item in allFields)
                    {
                        columns[i] = item.Value.Name;
                        i++;
                    }
                }
                string commandText = SqlConvert.ToRetrieveCommand(this.EntityName, allFields, id, columns);
                DataTable dt = EntityDal.Retrieve(commandText);
                if (dt != null)
                {
                    Dictionary<string, object> jo = new Dictionary<string, object>();
                    foreach (var item in columns)
                    {
                        switch (allFields[item].Type)
                        {
                            case FieldType.key:
                            case FieldType.nvarchar:
                            case FieldType.ntext:
                            case FieldType.image:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, dt.Rows[0][item].ToString());

                                    break;
                                }
                            case FieldType.datetime:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, DateTime.Parse(dt.Rows[0][item].ToString()).ToString("yyyy-MM-dd HH:mm:ss"));

                                    break;
                                }
                            case FieldType.date:
                                {

                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, DateTime.Parse(dt.Rows[0][item].ToString()).ToString("yyyy-MM-dd"));

                                    break;
                                }
                            case FieldType.picklist:
                            case FieldType.@int:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, int.Parse(dt.Rows[0][item].ToString()));

                                    break;
                                }
                            case FieldType.bit:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, dt.Rows[0][item].ToString() == "True");
                                    break;
                                }
                            case FieldType.@float:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                        jo.Add(item, double.Parse(dt.Rows[0][item].ToString()));
                                    break;
                                }
                            case FieldType.lookup:
                                {
                                    if (dt.Rows[0][item] is DBNull)
                                        jo.Add(item, null);
                                    else
                                    {
                                        var jef = new JObject();
                                        jef.Add("id", dt.Rows[0][item].ToString());
                                        jef.Add("name", dt.Rows[0][item + "Name"].ToString());
                                        jef.Add("entityname", allFields[item].LookupEntityName);
                                        jo.Add(item, jef);
                                    }
                                    break;
                                }
                        }

                    }
                    return jo;
                }
                return null;
            }
        }

        /// <summary>
        /// 更新记录
        /// </summary>
        /// <param name="json">jsonEntity</param>
        public string Update(string json)
        {
            Core core = new Core(EntityName);
            Dictionary<string, Field> allFields = core.GetFields();//当前实体的所有字段
            Dictionary<string, object> dicValue = JsonEntityToDictionary(json, allFields);
            return Update(dicValue);
        }

        /// <summary>
        /// 更新记录
        /// </summary>
        /// <param name="entity">要更新的字段名及其值（字段名全部小写）</param>
        /// <returns></returns>
        public string Update(Dictionary<string, object> entity)
        {
            string keyfieldname = this.EntityName + "id";
            if ((!entity.ContainsKey(keyfieldname))
                || entity[keyfieldname] == null
                || string.IsNullOrWhiteSpace(entity[keyfieldname].ToString()))
            {
                throw new CustomException(CustomExceptionState.Other, "未提供更新记录的主键字段(" + keyfieldname + ")");
            }

            if (!IsHaveRight(new Guid(entity[keyfieldname].ToString()), AccessRight.WRITE))
                throw new CustomException(CustomExceptionState.NoUpdatePrivilege, "没有更新记录的权限");

            EntityReference ModifiedBy = new EntityReference();
            ModifiedBy.id = this.CurrentUserId;
            ModifiedBy.entityname = "systemuser";

            entity["modifiedby"] = ModifiedBy;
            entity["modifiedon"] = DateTime.Now;

            entity.Remove("createdby");
            entity.Remove("createdon");
            entity.Remove("owninguser");
            entity.Remove("owningbusinessunit");
            entity.Remove("deletionstatecode");
            bool PluginState;
            //更新前Plugin触发
            try
            {
                PluginState = executePlugin(30, entity, this.CurrentUserId);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.BeforeUpdatePluginCrash, "执行更新前Plugin错误！" + ee.Message));
            }
            if (!PluginState)
            {
                throw (new CustomException(CustomExceptionState.UpdateForbidedByBeforePlugin, "Plugin阻止更新！"));
            }

            string id = service.Update(entity);

            //更新后Plugin触发
            try
            {
                executePlugin(40, entity, this.CurrentUserId);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.AfterUpdatePluginCrash, "执行更新后Plugin错误！" + ee.Message));
            }

            return id;
        }

        private string Update(Dictionary<string, object> entity, Dictionary<string, Field> allFields)
        {
            string commandText = SqlConvert.ToUpdateCommnad(this.EntityName, entity, allFields);
            EntityDal.Update(commandText);
            return entity[this.EntityName + "id"].ToString();
        }

        /// <summary>
        /// 删除记录
        /// </summary>
        /// <param name="id">记录Id</param>
        public void Delete(Guid id)
        {
            if (IsHaveRight(id, AccessRight.DELETE))
            {
                service.Delete(id);
            }
            else
            {
                throw new CustomException(CustomExceptionState.NoDeletePrivilege, "没有硬删除记录的权限" + this.EntityName + "," + id.ToString());
            }
        }

        /// <summary>
        /// 软删记录
        /// </summary>
        /// <param name="id">记录ID</param>
        public void SoftDelete(Guid id)
        {
            if (!IsHaveRight(id, AccessRight.DELETE))
                throw new CustomException(CustomExceptionState.NoDeletePrivilege, "没有软删除记录的权限" + this.EntityName + "," + id.ToString());

            Dictionary<string, object> dicValue = new Dictionary<string, object>();
            dicValue[this.EntityName + "id"] = id;

            EntityReference ModifiedBy = new EntityReference();
            ModifiedBy.id = this.CurrentUserId;
            ModifiedBy.entityname = "systemuser";
            dicValue["modifiedby"] = ModifiedBy;
            dicValue["modifiedon"] = DateTime.Now;
            dicValue["deletionstatecode"] = 1;

            //删除前Plugin触发
            bool PluginState;
            try
            {
                PluginState = executePlugin(50, id, this.CurrentUserId);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.BeforeDeletePluginCrash, "执行删除前Plugin错误！" + ee.Message));
            }
            if (!PluginState)
            {
                throw (new CustomException(CustomExceptionState.DeleteForbidedByBeforeDeletePlugin, "Plugin阻止更新！"));
            }
            service.Update(dicValue);

            //删除后Plugin触发
            try
            {
                if (!executePlugin(60, id, this.CurrentUserId))
                {
                }
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.AfterDeletePluginCrash, "执行删除后Plugin错误！" + ee.Message));
            }
        }

        /// <summary>
        /// 恢复软删记录
        /// </summary>
        /// <param name="id">记录ID</param>
        public void RecoverSoftDelete(Guid id)
        {
            if (!IsHaveRight(id, AccessRight.DELETE))
                throw new CustomException(CustomExceptionState.NoDeletePrivilege, "没有恢复软删除记录的权限" + this.EntityName + "," + id.ToString());

            Dictionary<string, object> dicValue = new Dictionary<string, object>();
            dicValue[this.EntityName + "id"] = id;

            EntityReference ModifiedBy = new EntityReference();
            ModifiedBy.id = this.CurrentUserId;
            ModifiedBy.entityname = "systemuser";
            dicValue["modifiedby"] = ModifiedBy;
            dicValue["modifiedon"] = DateTime.Now;
            dicValue["deletionstatecode"] = 0;



            service.Update(dicValue);

        }


        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="select">查询的字段</param>
        /// <param name="filter">查询条件</param>
        /// <param name="order">排序（例: fullname desc）</param>
        /// <param name="pageNum">要查询的页码</param>
        /// <param name="pageSize">每页记录条数</param>
        /// <returns></returns>
        public string RetrieveMultiple(string[] select, string filter, string order, int pageNum, int pageSize)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);

            }
            return JsonConvert.SerializeObject(RetrieveMultiple_List(select, filterEx, order, pageNum, pageSize));
        }

        public Dictionary<string, object> RetrieveMultiple_List(string[] select, FilterExpression filter, string order, int pageNum, int pageSize)
        {
            if (select == null || select.Length == 0)
            {
                throw new CustomException(CustomExceptionState.Other, "The first parameter(select) can not be null in RetrieveMultiple!");
            }
            return RetrieveMultiple(select, null, filter, order, pageNum, pageSize);
        }




        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="viewName">视图名称</param>
        /// <param name="filter">查询条件</param>
        /// <param name="order">排序（例: fullname desc）</param>
        /// <param name="pageNum">要查询的页码</param>
        /// <param name="pageSize">每页记录条数</param>
        /// <returns></returns>
        public string RetrieveMultiple(string viewName, string filter, string order, int pageNum, int pageSize)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);

            }
            return JsonConvert.SerializeObject(RetrieveMultiple_List(viewName, filterEx, order, pageNum, pageSize));
        }
        public Dictionary<string, object> RetrieveMultiple_List(string viewName, FilterExpression filter, string order, int pageNum, int pageSize)
        {
            if (string.IsNullOrWhiteSpace(viewName))
            {
                throw new CustomException(CustomExceptionState.Other, "The first parameter(viewName) can not be null in RetrieveMultiple!");
            }
            return RetrieveMultiple(null, viewName, filter, order, pageNum, pageSize);
        }

        #region 获取上一页、下一页数据
        public string RetrievePreviousPage(string viewName, string filter, string order, int pageSize, string lastOrderValue, Guid lastId)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);

            }
            return JsonConvert.SerializeObject(RetrievePreviousPage_List(viewName, filterEx, order, pageSize, lastOrderValue, lastId));
        }

        public List<Dictionary<string, object>> RetrievePreviousPage_List(string viewName, FilterExpression filter, string order, int pageSize, string lastOrderValue, Guid lastId)
        {
            if (string.IsNullOrWhiteSpace(viewName))
            {
                throw new CustomException(CustomExceptionState.Other, "The first parameter(viewName) can not be null in RetrieveNextPage!");
            }
            return RetrievePreviousOrNextPage(null, viewName, filter, order, pageSize, lastOrderValue, lastId, RetrievePageAction.PreviousPage);
        }
        public string RetrieveNextPage(string viewName, string filter, string order, int pageSize, string lastOrderValue, Guid lastId)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);
            }
            return JsonConvert.SerializeObject(RetrieveNextPage_List(viewName, filterEx, order, pageSize, lastOrderValue, lastId));
        }
        public List<Dictionary<string, object>> RetrieveNextPage_List(string viewName, string filter, string order, int pageSize, string lastOrderValue, Guid lastId)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);
            }
            return RetrieveNextPage_List(viewName, filterEx, order, pageSize, lastOrderValue, lastId);
        }
        public List<Dictionary<string, object>> RetrieveNextPage_List(string viewName, FilterExpression filter, string order, int pageSize, string lastOrderValue, Guid lastId)
        {
            if (string.IsNullOrWhiteSpace(viewName))
            {
                throw new CustomException(CustomExceptionState.Other, "The first parameter(viewName) can not be null in RetrieveNextPage!");
            }
            return RetrievePreviousOrNextPage(null, viewName, filter, order, pageSize, lastOrderValue, lastId, RetrievePageAction.NextPage);
        }
        #endregion


        /// <summary>
        /// 分配负责人与用户部门
        /// </summary>
        /// <param name="ID">字段主键的键值</param>
        /// <param name="OwingUser">分配给该记录的负责人ID（为Guid.Empty时保持原负责人不变）</param>
        /// <param name="OwingBusinessUnit">分配给该记录的业务部门ID（为Guid.Empty时保持原业务部门不变）</param>
        public void Assign(Guid ID, Guid OwingUser)
        {
            if (!IsHaveRight(ID, AccessRight.ASSIGN))
                throw new CustomException(CustomExceptionState.NoAssignPrivilege, "没有分派记录的权限" + this.EntityName + "" + ID.ToString());
            bool PluginState;
            //分派前Plugin触发
            try
            {
                PluginState = executePlugin(70, ID, this.CurrentUserId, OwingUser);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.BeforeAssignPluginCrash, "执行分派前Plugin错误！" + ee.Message));
            }
            if (!PluginState)
            {
                throw (new CustomException(CustomExceptionState.AssignForbidedByBeforeAsignPlugin, "Plugin阻止分派！"));
            }

            EntityDal.Assign(ID, OwingUser);

            //分派后Plugin触发
            try
            {
                executePlugin(80, ID, this.CurrentUserId, OwingUser);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.AfterAssignPluginCrash, "执行分派后Plugin错误！" + ee.Message));
            }

        }

        /// <summary>
        /// 获取N2N中间表名
        /// </summary>
        /// <param name="entityAname">主实体(将记录关联到哪个实体中)</param>
        /// <summary>
        public void GetN2NEntity(string entityAname)
        {

        }
        /// N2N添加记录
        /// </summary>
        /// <param name="ids">添加字段主键列表</param>
        /// <param name="entityAname">主实体(将记录关联到哪个实体中)</param>
        /// <param name="linkentityid">主实体ID</param>
        public DataSet N2NOpeate(string ids, string entityM, string entityB, string entityA, string linkentityid, string type)
        {
            DataSet ds = new EntityLinkDAL().OpeateN2N_toSql(ids, entityM, entityB, entityA, linkentityid, type);
            return ds;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="order"></param>
        /// <param name="filterData"></param>
        /// <param name="ViewName"></param>
        /// <param name="EntityA">主实体名</param>
        /// <param name="EntityM">中间表名</param>
        /// <param name="aid">主记录（EntityA）的guid</param>
        /// <param name="pageNum"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public string RetrieveMultipleN2NByView(string order, string filter, string viewName, string EntityA, string EntityM, Guid aid, int pageNum, int pageSize)
        {
            FilterExpression filterEx = null;
            if (!string.IsNullOrWhiteSpace(filter))
            {
                filterEx = JsonConvert.DeserializeObject<FilterExpression>(filter);

            }
            return JsonConvert.SerializeObject(RetrieveMultipleN2N_List(viewName, order, filterEx, EntityA, EntityM, aid, pageNum, pageSize));

        }

        public Dictionary<string, object> RetrieveMultipleN2N_List(string viewName, string order, FilterExpression filter, string EntityA, string EntityM, Guid aid, int pageNum, int pageSize)
        {
            if (string.IsNullOrWhiteSpace(viewName))
            {
                throw new CustomException(CustomExceptionState.Other, "The first parameter(viewName) can not be null in RetrieveMultipleN2N_List!");
            }
            return RetrieveMultipleN2N(null, viewName, filter, order, EntityA, EntityM, aid, pageNum, pageSize);
        }
        #endregion


        #region private方法

        private bool IsHaveRight(Guid Id, AccessRight access)
        {
            bool ishaveright = new PrivilegeDAL().IsHaveRight(this.EntityName, Id, this.CurrentUserId, (int)access);
            return ishaveright;
        }

        private bool IsHaveCreateRight(Guid currentUserId, Guid currentBusinessId, Guid owningUserId, Guid owningBusinessId)
        {
            bool ishaveright = new PrivilegeDAL().IsHaveCreateRight(this.EntityName, currentUserId, currentBusinessId, owningUserId, owningBusinessId);
            return ishaveright;
        }

        private Guid Create(Dictionary<string, object> entity, Dictionary<string, Field> allFields)
        {
            //当前用户
            EntityReference currUser = new EntityReference()
            {
                id = this.CurrentUserId,
                entityname = "SystemUser"
            };

            //当前部门
            EntityReference currbus = new EntityReference()
            {
                id = this.CurrentBusinessId,
                entityname = "BusinessUnit"
            };
            //负责人、负责部门
            if (entity.ContainsKey("owninguser")
                && entity["owninguser"] != null)
            {
                //设置OwningBusinessUnit
                EntityReference owningbus = new EntityReference()
                {
                    id = new Guid(new SystemUserDAL().GetSystemUserById(((EntityReference)entity["owninguser"]).id.Value).Rows[0]["BusinessUnitId"].ToString()),
                    entityname = "BusinessUnit"
                };
                entity["owningbusinessunit"] = owningbus;

            }
            else  //负责人没有指定时，设置默值为当前用户
            {
                entity["owninguser"] = currUser;
                entity["owningbusinessunit"] = currbus;
            }

            //权限
            if (!IsHaveCreateRight(this.CurrentUserId, currbus.id.Value, ((EntityReference)entity["owninguser"]).id.Value, ((EntityReference)entity["owningbusinessunit"]).id.Value))
            {
                throw new CustomException(CustomExceptionState.NoCreatePrivilege, "没有创建该记录的权限,entityname:" + this.EntityName);
            }


            //主键
            string keyfieldname = this.EntityName + "id";
            if ((!entity.ContainsKey(keyfieldname)) || entity[keyfieldname] == null || string.IsNullOrWhiteSpace(entity[keyfieldname].ToString()))
            {
                entity[keyfieldname] = Guid.NewGuid();
            }
            if (EntityName == "systemuser")
            {
                entity["owninguser"] = new EntityReference()
                {
                    id = (Guid)entity[keyfieldname],
                    entityname = "SystemUser"
                };
                entity["userimg"] = "/uploadfiles/userimg/default.png";
            }
            entity["createdby"] = currUser;
            entity["createdon"] = DateTime.Now;
            entity["modifiedby"] = currUser;
            entity["modifiedon"] = DateTime.Now;
            entity["deletionstatecode"] = 0;

            StringBuilder sbColumn = new StringBuilder();
            StringBuilder sbValue = new StringBuilder();

            //保存前Plugin触发
            bool PluginState;
            try
            {
                PluginState = executePlugin(10, entity, this.CurrentUserId);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.BeforeCreatePluginCrash, "执行Plugin错误！" + ee.Message));
            }
            if (!PluginState)
            {
                throw (new CustomException(CustomExceptionState.CreateForbidedByBeforeCreatePlugin, "Plugin阻止保存！"));
            }

            #region 拼接SQL
            foreach (KeyValuePair<string, object> item in entity)
            {

                sbColumn.Append(string.Format(" {0},", item.Key));

                switch (allFields[item.Key].Type)
                {
                    case FieldType.key:
                    case FieldType.nvarchar:
                    case FieldType.ntext:
                    case FieldType.image:
                        {
                            if (item.Value != null)
                                sbValue.Append(string.Format(" '{0}',", item.Value.ToString().Replace("'", "''")));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                    case FieldType.datetime:
                        {
                            if (item.Value != null)
                                sbValue.Append(string.Format(" '{0}',", ((DateTime)item.Value).ToString("yyyy-MM-dd HH:mm:ss")));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                    case FieldType.date:
                        {
                            if (item.Value != null)
                                sbValue.Append(string.Format(" '{0}',", ((DateTime)item.Value).ToString("yyyy-MM-dd")));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                    case FieldType.picklist:
                    case FieldType.@int:
                    case FieldType.bit:
                    case FieldType.@float:
                        {
                            if (item.Value != null)
                                sbValue.Append(string.Format(" {0},", item.Value.ToString()));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                    case FieldType.lookup:
                        {
                            if (item.Value != null && ((EntityReference)item.Value).id.ToString() != "")
                                sbValue.Append(string.Format(" '{0}',", ((EntityReference)item.Value).id.ToString()));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                    case FieldType.password:
                        {
                            if (item.Value != null)
                                sbValue.Append(string.Format(" '{0}',", System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(item.Value.ToString(), "MD5")));
                            else
                                sbValue.Append("null,");
                            break;
                        }
                }
            }
            #endregion

            EntityDal.Create(sbColumn.ToString().TrimEnd(','), sbValue.ToString().TrimEnd(','));


            //保存后Plugin触发
            try
            {
                executePlugin(20, entity, this.CurrentUserId);
            }
            catch (Exception ee)
            {
                throw (new CustomException(CustomExceptionState.AfterCreatePluginCrash, "执行保存后Plugin错误！" + ee.Message));
            }


            return new Guid(entity[keyfieldname].ToString());


        }

        //modify:kyzhao 2016-06-14 新视图配置查询数据
        private Dictionary<string, object> RetrieveMultiple(string[] select, string viewName, FilterExpression filter, string order, int pageNum, int pageSize)
        {
            Core core = new Core(EntityName);
            int startRow = pageNum * pageSize + 1, endRow = (pageNum + 1) * pageSize;


            //Dictionary<string, Field> allFields = core.GetViewFields();//当前实体的所有字段
            Dictionary<string, Field> allFields = core.GetViewAllFields(viewName);
            Dictionary<string, Field> selectFields = new Dictionary<string, Field>();

            #region order参数处理
            if (string.IsNullOrWhiteSpace(order))
                order = "";
            order = order.ToLower().Trim();
            string orderFieldName = "";
            string orderType = "asc";
            if (!string.IsNullOrWhiteSpace(order))
            {
                string[] orderData = order.Split(' ');
                orderFieldName = orderData[0];
                if (orderData.Length > 1 && orderData[1].ToLower() == "desc")
                {
                    orderType = "desc";
                }
                if (CheckFieldName(allFields, orderFieldName))
                {
                    if (orderData.Length > 1 && orderData[1].ToLower() == "desc")
                    {
                        orderType = "desc";
                    }
                }
                else
                {
                    throw new Exception("Parameter ‘order’ error in RetrieveMultiple！");
                }
            }
            if (string.IsNullOrWhiteSpace(orderFieldName))
            {
                order = this.EntityName + "id";
            }
            else
            {
                order = "[" + orderFieldName + "] " + orderType;
            }
            #endregion

            StringBuilder sbSelect = new StringBuilder();
            #region 最终查询字段处理
            if (select != null)
            {
                if (select.Length == 0)
                {
                    throw new Exception("Length of the Parameter(select) can not be 0 in RetrieveMultiple!");
                }
                for (int i = 0; i < select.Length; i++)
                {
                    string selectCloumn = select[i].ToLower();
                    if (!allFields.ContainsKey(selectCloumn))
                        throw new Exception("Parameter(select) Error in RetrieveMultiple!");
                    if (!selectFields.ContainsKey(selectCloumn))
                        selectFields.Add(selectCloumn, allFields[selectCloumn]);
                }
            }
            else if (!string.IsNullOrWhiteSpace(viewName))
            {
                selectFields = core.GetViewFields(viewName);
                string keyFieldName = (this.EntityName + "id").ToLower();
                if (!selectFields.ContainsKey(keyFieldName))
                {
                    selectFields.Add(keyFieldName, new Field() { Name = keyFieldName, Type = FieldType.key });
                }
            }
            else
            {
                throw new Exception("Parameters(‘select’ and ‘viewName’)Error in RetrieveMultiple!");
            }

            sbSelect.Append(string.Join(",", selectFields.Keys.ToArray<string>()));
            foreach (KeyValuePair<string, Field> kv in selectFields)
            {
                if (kv.Value.Type.Value == FieldType.lookup)
                {
                    //拼接Lookup查询字段
                    sbSelect.Append(string.Format(@",{0}name", kv.Key));
                }
            }
            #endregion

            StringBuilder sbSelectAll = new StringBuilder();
            StringBuilder sbJoins = new StringBuilder();


            string where = "";
            #region 查询条件处理
            //视图中的查询条件
            if (select == null && (!string.IsNullOrWhiteSpace(viewName)))
            {
                where = EntityDal.GetViewFilter(this.EntityName, viewName);
            }
            //传入的查询条件
            if (filter != null)
            {
                ExpressionConvert ec = new ExpressionConvert(this.EntityName, allFields, this.CurrentUserId, this.CurrentBusinessId);
                string filterString = ec.FilterConvert(filter);
                if (!string.IsNullOrWhiteSpace(filterString))
                {
                    if (string.IsNullOrWhiteSpace(where))
                    {
                        where = filterString;
                    }
                    else
                    {
                        where += " and " + filterString;
                    }
                }
            }
            where = (string.IsNullOrWhiteSpace(where) ? "" : string.Format(" WHERE {0} ", where));
            #endregion
            DataSet ds = EntityDal.RetrieveMultipleNew(viewName, where, EntityName, startRow, endRow, order, this.CurrentUserId);
            int length = (int)ds.Tables[1].Rows[0][0];

            Dictionary<string, object> listInfo = new Dictionary<string, object>();
            List<Dictionary<string, object>> ja = DataTableToJsonEntityList(ds.Tables[0], selectFields);
            listInfo.Add("List", ja);
            listInfo.Add("Total", length);
            listInfo.Add("Size", pageSize);
            listInfo.Add("Index", pageNum);

            return listInfo;

        }

        //modifyby:kyzhao 手机端新视图配置查询数据
        private List<Dictionary<string, object>> RetrievePreviousOrNextPage(string[] select, string viewName, FilterExpression filter, string order, int pageSize, string lastOrderValue, Guid lastId, RetrievePageAction pageAction)
        {
            Core core = new Core(EntityName);

            Dictionary<string, Field> allFields = core.GetViewAllFields(viewName);//当前实体的所有字段
            Dictionary<string, Field> selectFields = new Dictionary<string, Field>();

            #region order参数处理
            if (string.IsNullOrWhiteSpace(order)) throw new CustomException(CustomExceptionState.Other, "Parameter‘order’can not be NullOrWhiteSpace！");
            string[] orderData = order.ToLower().Trim().Split(' ');
            string orderFieldName = orderData[0];
            string orderType = "asc";
            if (!CheckFieldName(allFields, orderFieldName)) throw new CustomException(CustomExceptionState.Other, "Parameter ‘order’ error in RetrieveMultiple！");
            if (orderData.Length > 1 && orderData[1].ToLower() == "desc") orderType = "desc";
            orderFieldName = "[" + orderFieldName + "] ";
            #endregion

            StringBuilder sbSelect = new StringBuilder();
            #region 最终查询字段处理
            if (select != null)
            {
                if (select.Length == 0) throw new Exception("Length of the Parameter(select) can not be 0 in RetrieveMultiple!");
                for (int i = 0; i < select.Length; i++)
                {
                    string selectCloumn = select[i].ToLower();
                    if (!allFields.ContainsKey(selectCloumn)) throw new Exception("Parameter(select) Error in RetrieveMultiple!");
                    if (!selectFields.ContainsKey(selectCloumn)) selectFields.Add(selectCloumn, allFields[selectCloumn]);
                }
            }
            else if (!string.IsNullOrWhiteSpace(viewName))
            {
                selectFields = core.GetViewFields(viewName);
                string keyFieldName = (this.EntityName + "id").ToLower();
                if (!selectFields.ContainsKey(keyFieldName))
                {
                    selectFields.Add(keyFieldName, new Field() { Name = keyFieldName, Type = FieldType.key });
                }
            }
            else
            {
                throw new Exception("Parameters(‘select’ and ‘viewName’)Error in RetrieveMultiple!");
            }

            sbSelect.Append(string.Join(",", selectFields.Keys.ToArray<string>()));
            foreach (KeyValuePair<string, Field> kv in selectFields)
            {
                if (kv.Value.Type.Value == FieldType.lookup)
                {
                    //拼接Lookup查询字段
                    sbSelect.Append(string.Format(@",{0}name", kv.Key));
                }
            }
            #endregion

            string where = "";
            #region 查询条件处理
            //视图中的查询条件
            if (select == null && (!string.IsNullOrWhiteSpace(viewName)))
            {
                where = EntityDal.GetViewFilter(this.EntityName, viewName);
            }
            //传入的查询条件
            if (filter != null)
            {
                ExpressionConvert ec = new ExpressionConvert(this.EntityName, allFields, this.CurrentUserId, this.CurrentBusinessId);
                string filterString = ec.FilterConvert(filter);
                if (!string.IsNullOrWhiteSpace(filterString))
                {
                    if (string.IsNullOrWhiteSpace(where))
                    {
                        where = filterString;
                    }
                    else
                    {
                        where += " and " + filterString;
                    }
                }
            }
            where = (string.IsNullOrWhiteSpace(where) ? "" : string.Format(" WHERE {0} ", where));
            #endregion

            DataSet ds = EntityDal.RetrieveMultipleMobile(viewName, where, EntityName, orderFieldName, this.CurrentUserId, lastOrderValue, lastId.ToString(), orderType, pageSize.ToString());
            //int length = (int)ds.Tables[1].Rows[0][0];

            List<Dictionary<string, object>> ja = DataTableToJsonEntityList(ds.Tables[0], selectFields);

            return ja;



        }

        private Dictionary<string, object> RetrieveMultipleN2N(string[] select, string viewName, FilterExpression filter, string order, string EntityA, string EntityM, Guid aid, int pageNum, int pageSize)
        {
            Core core = new Core(EntityName);
            int startRow = pageNum * pageSize + 1, endRow = (pageNum + 1) * pageSize;


            Dictionary<string, Field> allFields = core.GetFields();//当前实体的所有字段
            Dictionary<string, Field> selectFields = new Dictionary<string, Field>();

            #region order参数处理
            if (string.IsNullOrWhiteSpace(order))
                order = "";
            order = order.ToLower().Trim();
            string orderFieldName = "";
            string orderType = "asc";
            if (!string.IsNullOrWhiteSpace(order))
            {
                string[] orderData = order.Split(' ');
                orderFieldName = orderData[0];
                if (CheckFieldName(allFields, orderFieldName))
                {
                    if (orderData.Length > 1 && orderData[1].ToLower() == "desc")
                    {
                        orderType = "desc";
                    }
                }
                else
                {
                    throw new Exception("Parameter ‘order’ error in RetrieveMultiple！");
                }
            }
            if (string.IsNullOrWhiteSpace(orderFieldName))
            {
                order = this.EntityName + "id";
            }
            else
            {
                order = orderFieldName + " " + orderType;
            }
            #endregion

            StringBuilder sbSelect = new StringBuilder();
            #region 最终查询字段处理
            if (select != null)
            {
                if (select.Length == 0)
                {
                    throw new Exception("Length of the Parameter(select) can not be 0 in RetrieveMultiple!");
                }
                for (int i = 0; i < select.Length; i++)
                {
                    string selectCloumn = select[i].ToLower();
                    if (!allFields.ContainsKey(selectCloumn))
                        throw new Exception("Parameter(select) Error in RetrieveMultiple!");
                    if (!selectFields.ContainsKey(selectCloumn))
                        selectFields.Add(selectCloumn, allFields[selectCloumn]);
                }
            }
            else if (!string.IsNullOrWhiteSpace(viewName))
            {
                selectFields = core.GetFields(viewName);
                string keyFieldName = (this.EntityName + "id").ToLower();
                if (!selectFields.ContainsKey(keyFieldName))
                {
                    selectFields.Add(keyFieldName, new Field() { Name = keyFieldName, Type = FieldType.key });
                }
            }
            else
            {
                throw new Exception("Parameters(‘select’ and ‘viewName’)Error in RetrieveMultiple!");
            }

            sbSelect.Append(string.Join(",", selectFields.Keys.ToArray<string>()));
            foreach (KeyValuePair<string, Field> kv in selectFields)
            {
                if (kv.Value.Type.Value == FieldType.lookup)
                {
                    //拼接Lookup查询字段
                    sbSelect.Append(string.Format(@",{0}name", kv.Key));
                }
            }
            #endregion

            StringBuilder sbSelectAll = new StringBuilder();
            StringBuilder sbJoins = new StringBuilder();
            #region 原始表关联Lookup后查询字段及关联语句
            sbSelectAll.Append("base.*");
            int lookupIndex = 0;
            sbJoins.Append(string.Format(@" INNER JOIN {0} m WITH(NOLOCK) on m.{1}Id=base.{1}Id and m.{2}Id='{3}' ", EntityM, EntityName, EntityA, aid));
            foreach (KeyValuePair<string, Field> kv in allFields)
            {
                if (kv.Value.Type.Value == FieldType.lookup)
                {
                    Field lookupField = kv.Value;
                    //拼接Lookup查询字段
                    sbSelectAll.Append(string.Format(@",j{0}.{1} AS {2}name", lookupIndex, lookupField.LookupPrimaryAtt, kv.Key));

                    //拼接Lookup关联表
                    sbJoins.Append(string.Format(@" LEFT JOIN {0} j{1} WITH(NOLOCK) ON base.{2}=j{1}.{0}Id "
                       , lookupField.LookupEntityName, lookupIndex, kv.Key));
                    lookupIndex++;
                }
            }
            #endregion

            string where = "";
            #region 查询条件处理
            //视图中的查询条件
            if (select == null && (!string.IsNullOrWhiteSpace(viewName)))
            {
                where = EntityDal.GetViewFilter(this.EntityName, viewName);
            }
            //传入的查询条件
            if (filter != null)
            {
                ExpressionConvert ec = new ExpressionConvert(this.EntityName, allFields, this.CurrentUserId, this.CurrentBusinessId);
                string filterString = ec.FilterConvert(filter);
                if (!string.IsNullOrWhiteSpace(filterString))
                {
                    if (string.IsNullOrWhiteSpace(where))
                    {
                        where = filterString;
                    }
                    else
                    {
                        where += " and " + filterString;
                    }
                }
            }
            where = (string.IsNullOrWhiteSpace(where) ? "" : string.Format(" WHERE {0} ", where));
            #endregion

            string wherePrivilege = "";
            #region 权限条件
            Privilege privilege = core.GetPrivilege(this.CurrentUserId);
            switch (privilege.READ)
            {
                case DepthMask.User:
                    wherePrivilege = string.Format(@" where base.OwningUser = '{0}' ", this.CurrentUserId);
                    break;
                case DepthMask.BusinessUnit:
                    wherePrivilege = string.Format(@" where base.OwningBusinessUnit = '{0}' ", this.CurrentBusinessId);
                    break;
                case DepthMask.BusinessUnitAndChildren:
                    wherePrivilege = string.Format(@" where base.OwningBusinessUnit in (select biz.SubBusinessId from BusinessUnitMap as biz where biz.BusinessId = '{0}') ", this.CurrentBusinessId);
                    break;
                case DepthMask.Organization:
                    //无须额外条件;
                    break;
                default:
                    //无权限
                    wherePrivilege = " where 0=1 ";
                    break;
            }
            #endregion

            DataSet ds = EntityDal.RetrieveMultiple(sbSelect.ToString(), order, sbSelectAll.ToString(), EntityName, sbJoins.ToString(), wherePrivilege, where, startRow, endRow);
            int length = (int)ds.Tables[1].Rows[0][0];

            Dictionary<string, object> listInfo = new Dictionary<string, object>();
            List<Dictionary<string, object>> ja = DataTableToJsonEntityList(ds.Tables[0], selectFields);
            listInfo.Add("List", ja);
            listInfo.Add("Total", length);
            listInfo.Add("Size", pageSize);
            listInfo.Add("Index", pageNum);

            return listInfo;
        }

        private bool CheckFieldName(Dictionary<string, Field> allFields, string fieldName)
        {
            if (!allFields.ContainsKey(fieldName))
            {
                string fieldNameTrim = fieldName.Replace("name", "");
                if (fieldName != (fieldNameTrim + "name")
                    || (!allFields.ContainsKey(fieldNameTrim))
                    || allFields[fieldNameTrim].Type.Value != FieldType.lookup)
                {
                    return false;
                }
            }
            return true;
        }

        private List<Dictionary<string, object>> DataTableToJsonEntityList(DataTable dt, Dictionary<string, Field> selectFields)
        {
            List<Dictionary<string, object>> ja = new List<Dictionary<string, object>>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                Dictionary<string, object> jo = new Dictionary<string, object>();
                foreach (KeyValuePair<string, Field> kv in selectFields)
                {
                    string item = kv.Key;
                    switch (kv.Value.Type)
                    {
                        case FieldType.key:
                        case FieldType.nvarchar:
                        case FieldType.ntext:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, dt.Rows[i][item].ToString());

                                break;
                            }
                        case FieldType.datetime:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, DateTime.Parse(dt.Rows[i][item].ToString()).ToString("yyyy-MM-dd HH:mm:ss"));

                                break;
                            }
                        case FieldType.date:
                            {

                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, DateTime.Parse(dt.Rows[i][item].ToString()).ToString("yyyy-MM-dd"));

                                break;
                            }
                        case FieldType.picklist:
                        case FieldType.@int:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, int.Parse(dt.Rows[i][item].ToString()));

                                break;
                            }
                        case FieldType.bit:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, dt.Rows[i][item].ToString() == "True");
                                break;
                            }
                        case FieldType.@float:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                    jo.Add(item, double.Parse(dt.Rows[i][item].ToString()));
                                break;
                            }
                        case FieldType.lookup:
                            {
                                if (dt.Rows[i][item] is DBNull)
                                    jo.Add(item, null);
                                else
                                {
                                    var jef = new JObject();
                                    jef.Add("id", dt.Rows[i][item].ToString());
                                    jef.Add("name", dt.Rows[i][item + "name"].ToString());
                                    jef.Add("entityname", kv.Value.LookupEntityName);
                                    jo.Add(item, jef);
                                }
                                break;
                            }
                    }

                }
                ja.Add(jo);
            }
            return ja;
        }

        private Dictionary<string, object> JsonEntityToDictionary(string data, Dictionary<string, Field> allFields)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();

            JObject jo = (JObject)JsonConvert.DeserializeObject(data);

            foreach (KeyValuePair<string, JToken> item in jo)
            {
                string fieldname = item.Key.ToLower();
                switch (allFields[fieldname].Type)
                {
                    case FieldType.key:
                    case FieldType.nvarchar:
                    case FieldType.ntext:
                    case FieldType.password:
                    case FieldType.image:
                        {
                            if (item.Value.Type != JTokenType.Null)
                                dic.Add(fieldname, item.Value.ToString());
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                    case FieldType.datetime:
                    case FieldType.date:
                        {
                            if (item.Value.Type != JTokenType.Null)
                                dic.Add(fieldname, DateTime.Parse(item.Value.ToString()));
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                    case FieldType.picklist:
                    case FieldType.@int:
                        {
                            if (item.Value.Type != JTokenType.Null)
                                dic.Add(fieldname, int.Parse(item.Value.ToString()));
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                    case FieldType.bit:
                        {
                            if (item.Value.Type != JTokenType.Null)
                                dic.Add(fieldname, item.Value.ToString().ToLower() == "true" ? 1 : 0);
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                    case FieldType.@float:
                        {
                            if (item.Value.Type != JTokenType.Null)
                                dic.Add(fieldname, double.Parse(item.Value.ToString()));
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                    case FieldType.lookup:
                        {
                            if (item.Value.Type != JTokenType.Null)
                            {
                                EntityReference entityReference = new EntityReference
                                {
                                    id = new Guid(item.Value["id"].ToString()),
                                    name = item.Value["name"].ToString(),
                                    entityname = item.Value["entityname"].ToString()
                                };
                                dic.Add(fieldname, entityReference);
                            }
                            else
                                dic.Add(fieldname, null);
                            break;
                        }
                }
            }
            return dic;
        }

        #endregion


        #region Plugin
        //创建、更新plugin
        public bool executePlugin(int type, Dictionary<string, object> entity, Guid currentUser)
        {
            Plugin p = new Plugin();
            DataRow[] plugins = p.getPlugins(this.EntityName, type);
            for (int i = 0; i < plugins.Length; i++)
            {


                if (!string.IsNullOrWhiteSpace(plugins[i]["StoredProcedure"].ToString()))
                {
                    try
                    {
                        p.execSP(plugins[i]["StoredProcedure"].ToString(), new Guid(entity[this.EntityName + "id"].ToString()), currentUser);
                    }
                    catch (Exception e)
                    {

                    }
                }
                else
                {

                    byte[] filesByte = File.ReadAllBytes(Config.PluginPath + plugins[i]["dll"]);
                    Assembly ass = Assembly.Load(filesByte);  //加载dll文件
                    Type tp = ass.GetType(plugins[i]["ClassName"].ToString());  //获取类名，必须 命名空间+类名
                    Object obj = Activator.CreateInstance(tp);  //建立实例
                    MethodInfo meth = tp.GetMethod(plugins[i]["PluginFunction"].ToString());  //获取方法
                    if (!(bool)(meth.Invoke(obj, new object[] { entity, currentUser })))
                    {
                        return false;
                    }

                }
            }
            return true;
        }
        //删除Plugin
        public bool executePlugin(int type, Guid entityid, Guid currentUser)
        {
            Plugin p = new Plugin();
            DataRow[] plugins = p.getPlugins(this.EntityName, type);
            for (int i = 0; i < plugins.Length; i++)
            {
                if (!string.IsNullOrWhiteSpace(plugins[i]["StoredProcedure"].ToString()))
                {
                    try
                    {
                        p.execSP(plugins[i]["StoredProcedure"].ToString(), entityid, currentUser);
                    }
                    catch (Exception e)
                    {

                    }
                }
                else
                {
                    byte[] filesByte = File.ReadAllBytes(Config.PluginPath + plugins[i]["dll"]);
                    Assembly ass = Assembly.Load(filesByte);  //加载dll文件
                    Type tp = ass.GetType(plugins[i]["ClassName"].ToString());  //获取类名，必须 命名空间+类名
                    Object obj = Activator.CreateInstance(tp);  //建立实例
                    MethodInfo meth = tp.GetMethod(plugins[i]["PluginFunction"].ToString());  //获取方法
                    if (!(bool)(meth.Invoke(obj, new object[] { entityid, currentUser })))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        //分派plugin
        public bool executePlugin(int type, Guid entityid, Guid currentUser, Guid assignUser)
        {
            Plugin p = new Plugin();
            DataRow[] plugins = p.getPlugins(this.EntityName, type);
            for (int i = 0; i < plugins.Length; i++)
            {
                if (!string.IsNullOrWhiteSpace(plugins[i]["StoredProcedure"].ToString()))
                {
                    try
                    {
                        p.execSP(plugins[i]["StoredProcedure"].ToString(), entityid, currentUser);
                    }
                    catch (Exception e)
                    {

                    }
                }
                else
                {
                    byte[] filesByte = File.ReadAllBytes(Config.PluginPath + plugins[i]["dll"]);
                    Assembly ass = Assembly.Load(filesByte);  //加载dll文件
                    Type tp = ass.GetType(plugins[i]["ClassName"].ToString());  //获取类名，必须 命名空间+类名
                    Object obj = Activator.CreateInstance(tp);  //建立实例
                    MethodInfo meth = tp.GetMethod(plugins[i]["PluginFunction"].ToString());  //获取方法
                    if (!(bool)(meth.Invoke(obj, new object[] { entityid, currentUser, assignUser })))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        #endregion
    }
    #endregion

    enum RetrievePageAction
    {
        NextPage, PreviousPage
    }
}